/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Game;

//import com.sun.java.swing.plaf.windows.resources.windows;
import java.awt.Color;
//import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.Toolkit;
import java.net.URL;
import java.util.ArrayList;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;
//import javax.swing.JOptionPane;

/**
 *
 * @author VO CHI DUNG
 */
public class MyGame {

    Player[] ArrayPlayer;
    MyCard[] CardReceived;
    int fisrtCardType;
    boolean IsBrokenHeart;
    ArrayList<int[]> listScore;
    int whoHasTurn;
    int whoHasFirstTurn;
    private static int EASY = 1;
    private static int NORMAL = 2;
    private static int HARD = 3;
    private boolean bPlayerSend;// = false;
    private int iPlayerUpdate = 0;

    public void startGame() {
        InitGame();

        boolean finishedGame = false;
        while (!finishedGame) {
            //Update();
            finishedGame = playRound();
        }
        JOptionPane.showMessageDialog(null, listScore.get(listScore.size() - 1)[0]);
        JOptionPane.showMessageDialog(null, listScore.get(listScore.size() - 1)[1]);
        JOptionPane.showMessageDialog(null, listScore.get(listScore.size() - 1)[2]);
        JOptionPane.showMessageDialog(null, listScore.get(listScore.size() - 1)[3]);
    }

    public void InitGame() {
        String[] PlayerName = new String[]{"My name", "West", "North", "East"};
        ArrayPlayer = new Player[4];
        for (int i = 0; i < 4; i++) {
            ArrayPlayer[i] = new Player();
            ArrayPlayer[i].setName(PlayerName[i]);
            ArrayPlayer[i].setPosToDraw(GlobalSettings.PosToDraws[i]);
            ArrayPlayer[i].setCardsDistance(GlobalSettings.CardsDistances[i]);
        }
        CardReceived = new MyCard[4];
        listScore = new ArrayList<int[]>();
        int arr[] = new int[]{0, 0, 0, 0};
        listScore.add(arr);
        IsBrokenHeart = false;
        fisrtCardType = -1;
        whoHasTurn = -1;
        whoHasFirstTurn = -1;
        setbPlayerSend(false);
    }

    /*
     * Create 52 Card for Game
     * 0: cơ
     * 1: rô
     * 2: chuồn
     * 3: bích
     */
    private MyCard[] createArrayCardForGame() {
        MyCard[] arrayCard = new MyCard[52];
        for (int type = 0; type < 4; type++) {
            for (int number = 2; number <= 14; number++) {
                int index = type * 13 + number - 2;

                int centerCardPos_X = (GlobalSettings.ScreenWidth - GlobalSettings.CardWidth) / 2;
                int centerCardPos_Y = (GlobalSettings.ScreenHeight - GlobalSettings.CardHeight) / 2;
                Point beginPos = new Point(centerCardPos_X, centerCardPos_Y);

                arrayCard[index] = new MyCard(number, type, beginPos);
            }
        }
        return arrayCard;
    }

    /*
     * Mix Card after finish the round
     */
    private int[] mixCard() {
        Random random = new Random();
        int[] arrayIndexCard = new int[52];
        for (int i = 0; i < arrayIndexCard.length; i++) {
            arrayIndexCard[i] = i + 1;
        }
        int index1 = 0;
        int index2 = 0;
        for (int i = 0; i < 100; i++) {
            index1 = random.nextInt(52);
            index2 = random.nextInt(52);
            if (index1 != index2) {
                arrayIndexCard[index2] = arrayIndexCard[index2] + arrayIndexCard[index1];
                arrayIndexCard[index1] = arrayIndexCard[index2] - arrayIndexCard[index1];
                arrayIndexCard[index2] = arrayIndexCard[index2] - arrayIndexCard[index1];
            }
        }
        return arrayIndexCard;
    }

    /*
     * Make deal card for four player
     */
    public void makeDeal(MyCard[] arrayCard, int[] arrayIndexCard) {
        for (int i = 0; i < arrayIndexCard.length; i++) {
            MyCard card = arrayCard[arrayIndexCard[i] - 1];
            ArrayPlayer[i % 4].addCard(card);
        }
    }

    public int getRound() {
        return listScore.size() + 1;
    }

    /*
     * kiểm tra xem vong chơi thứ mấy để biết hướng chuyển bài
     * 1: chuyen theo chieu kiem dong ho
     * 2: nguoc chieu kim dong ho
     * 3: doi dien
     * 0: khong chuyen
     */
    public int getDirection(int round) {
        return round / 4;
    }

    public void passCard(int direction) {
        if (direction == 0) {
            return;
        }
        // doi nguoi choi chon bai de chuyen
        boolean finishedChoose = true;
        while (finishedChoose) {
            // nhan xong
            finishedChoose = false;
        }
        switch (direction) {
            case 1:
                passDirectionLeft();
                break;
            case 2:
                passDirectionRight();
                break;
            case 3:
                passDirectionOpposite();
                break;
        }
    }

    /*
     * 0: nguoi choi 1
     * 1: nguoi choi 2
     * 2: nguoi choi 3
     * 3: nguoi choi 4
     */
    private int getPlayerHas2Club() {
        for (int i = 1; i < ArrayPlayer.length; i++) {
            if (ArrayPlayer[i].HasTwoClud()) {
                return i;
            }
        }
        return 0;
    }

    public void resetRound() {
        for (int i = 0; i < 4; i++) {
            CardReceived[i] = null;
        }
        IsBrokenHeart = false;
        for(int i=0;i<ArrayPlayer.length;i++)
            ArrayPlayer[i].reset();
        isFinishedMakeDeal = false;
    }

    public boolean isValidCard(MyCard card, int iPlayer) {
        int typeCard = card.getTypeCard();
        // Là người đầu tiên đánh trong lượt này
//        if (isFirstCardInTurn()) {
        if (whoHasFirstTurn == iPlayer) {
            // Người chơi đánh nước Cơ
            if (typeCard == 0) {
                //Trái tim bị vỡ
                if (IsBrokenHeart) {
                    fisrtCardType = typeCard;
                    return true;
                } else {// Trái tim chưa bị vỡ
                    return false;
                }
            } else {// Người chơi đánh không phải nước cơ
                fisrtCardType = typeCard;
                return true;
            }
            // không phải người đầu tiên đánh trong lượt này
        } else {
            if (typeCard == fisrtCardType) {
                return true;
            } else {
                if (ArrayPlayer[iPlayer].isHasTypeCard(fisrtCardType)) {
                    return false;
                } else {
                    if (typeCard == 0) {
                        IsBrokenHeart = true;
                    }
                    return true;
                }
            }
        }
    }

//    private boolean isFirstCardInTurn()
//    {
//        for(int index = 0; index < CardReceived.length-1;index++)
//            if(CardReceived[index]!=null)
//                return false;
//        return true;
//    }
    public int passTurn(int iPlayer) {
        ArrayPlayer[iPlayer].setbHasTurn(false);
        return (iPlayer + 1) % 4;
    }

    private void passDirectionLeft() {
        throw new UnsupportedOperationException("Not yet implemented");
    }

    private void passDirectionRight() {
        throw new UnsupportedOperationException("Not yet implemented");
    }

    private void passDirectionOpposite() {
        throw new UnsupportedOperationException("Not yet implemented");
    }

    private boolean isFinishedTurn() {
        int numReceivedCard = 0;
        for (int i = 0; i < CardReceived.length; i++) {
            if (CardReceived[i] != null) {
                numReceivedCard++;
            }
        }

        if (numReceivedCard == 4) {
            return true;
        }
        return false;
    }

    private int getWinerInTurn() {
        int winer = whoHasFirstTurn;
        for (int i = 0; i < CardReceived.length; i++) {
            if (CardReceived[i].getTypeCard() == fisrtCardType
                    && CardReceived[i].getNumberCard() > CardReceived[winer].getNumberCard()) {
                winer = i;
            }
        }
        return winer;
    }

    private int calculateScore() {
        int score = 0;
        for (int i = 0; i < CardReceived.length; i++) {
            if (CardReceived[i].getTypeCard() == 0) {
                score++;
            } else if (CardReceived[i].getTypeCard() == 3 && CardReceived[i].getNumberCard() == 12) {
                score += 13;
            }
        }
        return score;
    }

    public boolean isFinishRound() {
        if (ArrayPlayer[0].isEmptyListCard()) {
            return true;
        }
        return false;
    }

    private void updateListScore() {
        int[] arrayTemp = listScore.get(listScore.size() - 1);
        int scorePlayer1 = ArrayPlayer[0].getScore() + arrayTemp[0];
        int scorePlayer2 = ArrayPlayer[1].getScore() + arrayTemp[1];
        int scorePlayer3 = ArrayPlayer[2].getScore() + arrayTemp[2];
        int scorePlayer4 = ArrayPlayer[3].getScore() + arrayTemp[3];
        int[] arrayScore = new int[]{scorePlayer1, scorePlayer2, scorePlayer3, scorePlayer4};
        listScore.add(arrayScore);
    }

    private void updateCardReceiveForPlayer(int iplayer) {
        for (int i = 0; i < CardReceived.length; i++) {
            if (CardReceived[i].getTypeCard() == 0) {
                ArrayPlayer[iplayer].updateCardReceive(CardReceived[i]);
            }
            if (CardReceived[i].getTypeCard() == 3 && CardReceived[i].getNumberCard() == 12) {
                ArrayPlayer[iplayer].updateCardReceive(CardReceived[i]);
            }
        }
    }

    private boolean isFinishGame() {
        for (int i = 0; i < 4; i++) {
            if (listScore.get(listScore.size() - 1)[i] >= 100) {
                return true;
            }
        }
        return false;
    }

    public void DrawPlayerName(Graphics g) {
        Font font = new Font("Courier", Font.BOLD, 23);
        g.setFont(font);
        g.setColor(Color.WHITE);

        for (int i = 0; i < ArrayPlayer.length; i++) {
            g.drawString(ArrayPlayer[i].getName(), GlobalSettings.PosToDrawName[i].x, GlobalSettings.PosToDrawName[i].y);
        }
    }

    /*
     * Choi 1 hiep
     * false: hết 1 hiệp
     * true: kết thuc game
     */
    private boolean playRound() {
        resetRound();
        // tạo bộ bài
        MyCard[] arrayCard = createArrayCardForGame();
        // Sào bài
        int[] arrayIndexCard = mixCard();
        // Chia bài
        makeDeal(arrayCard, arrayIndexCard);
        
        // tạo bài cho ngươi choi
        createCardForPlayer();

        // kiem tra ai co 2 chuồng
        int indexfirstPlayer = getPlayerHas2Club();
        whoHasFirstTurn = indexfirstPlayer;
        ArrayPlayer[whoHasFirstTurn].UpdatedCard = true;
        iPlayerUpdate = whoHasFirstTurn;
        //while(!isFinishedMakeDeal);
        // Sap bai
        // sortListCard(0);

//       MyCard card = ArrayPlayer[indexfirstPlayer].sendCardTowClud();
//       addReceiveCard(card, indexfirstPlayer);
//       fisrtCardType = card.getTypeCard();
//       ArrayPlayer[indexfirstPlayer].removeCardInListCurrentCard(card);
//       indexfirstPlayer = passTurn(indexfirstPlayer);
        // vòng lặp chơi game
        do {
            indexfirstPlayer = playTurn(indexfirstPlayer);
        } while (indexfirstPlayer != -1 && indexfirstPlayer != -2);

        if (indexfirstPlayer == -1) {
            return false;// kết thúc 1 hiệp
        }
        return true;// kết thúc game
    }

    private void createCardForPlayer() {
        for (int i = 0; i < ArrayPlayer.length; i++) {
            if (i != 0) {
                ArrayPlayer[i].ChangeBackCards();
            }
            ArrayPlayer[i].initCardsPos();
        }

        ArrayPlayer[0].initCardsPos();
    }

    /*
     * Choi 1 luot
     * indexfirstPlayer: chỉ số của người chơi đánh đầu tiên trong lượt chơi này.
     * -2: kết thúc game
     * -1: kết thúc 1 hiệp
     * chi số người chơi: hết 1 lượt
     */
    private int playTurn(int indexfirstPlayer) {
        whoHasTurn = indexfirstPlayer;
        // ArrayPlayer[indexfirstPlayer].setbHasTurn(true);
        MyCard card = new MyCard();
        if (indexfirstPlayer != 0) {
            ArrayPlayer[0].setbHasTurn(false);
            boolean bInvalidCard = false;
            do {
                card = ArrayPlayer[indexfirstPlayer].computerPlay(CardReceived,
                        fisrtCardType,
                        whoHasFirstTurn == indexfirstPlayer,
                        IsBrokenHeart,
                        NORMAL);
                if (card != null) {
                    numberTemp = card.getNumberCard();
                    typeTemp = card.getTypeCard();
                    bInvalidCard = isValidCard(card, indexfirstPlayer);
                }
            } // kiem tra xem card danh co hop le khong
            while (!bInvalidCard);
            addReceiveCard(card, indexfirstPlayer);
            ArrayPlayer[indexfirstPlayer].removeCardInListCurrentCard(card);
        } else {
            ArrayPlayer[0].setbHasTurn(true);
            while (!bPlayerSend);
            bPlayerSend = false;
            ArrayPlayer[0].setbHasTurn(false);
        }
        if (isFinishedTurn()) {
            // Tinh xem ai la nguoi thang bai trong ván bài nay
            indexfirstPlayer = getWinerInTurn();
            whoHasFirstTurn = indexfirstPlayer;
            // kiem tra xem nguoi choi co duoc diem khong => nếu có thì cập nhật điểm cho người chơi thắng
            ArrayPlayer[indexfirstPlayer].updateScore(calculateScore());
            updateCardReceiveForPlayer(indexfirstPlayer);
            // thread sleep sau khi hoan thanh 1 turn đê nguoi choi thay duoc bai
            try {
                Thread.sleep(1000);
            } catch (InterruptedException ex) {
                Logger.getLogger(MyGame.class.getName()).log(Level.SEVERE, null, ex);
            }
            ResetCardReceived();
            if (isFinishRound()) {
                updateListScore();
                if (isFinishGame()) {
                    return -2;
                }
                return -1;
            }

            return indexfirstPlayer;
        } else {
            indexfirstPlayer = passTurn(indexfirstPlayer);
            return playTurn(indexfirstPlayer);
        }
    }

    private void ResetCardReceived() {
        CardReceived[0] = null;
        CardReceived[1] = null;
        CardReceived[2] = null;
        CardReceived[3] = null;
    }

    public void addReceiveCard(MyCard card, int indexPlayer) {
        MyCard cardTemp = new MyCard(card.getNumberCard(), card.getTypeCard(), null);
        CardReceived[indexPlayer] = cardTemp;
    }

    public void processCursor(int x, int y) {
        ArrayPlayer[0].processCursor(x, y);
    }

    public boolean processCardSend() {
        MyCard card = ArrayPlayer[0].processCardSend();
        if (card != null) {
            if (isValidCard(card, 0)) {
                addReceiveCard(card, 0);
                ArrayPlayer[0].removeCardInListCurrentCard(card);
                return true;
            }
        }
        return false;
    }

    public void DrawBackground(Graphics g, int width, int height) {
        String nameCard = "Resource/Background/bg8.jpg";

        ClassLoader loader = this.getClass().getClassLoader();
        URL cardPath = loader.getResource(nameCard);
        Image img = Toolkit.getDefaultToolkit().getImage(cardPath);

        Graphics2D g2D = (Graphics2D) g;
        g2D.drawImage(img, 0, 0, width, height, null);
    }

    /**
     * @return the bPlayerSend
     */
    public boolean isbPlayerSend() {
        return bPlayerSend;
    }

    /**
     * @param bPlayerSend the bPlayerSend to set
     */
    public void setbPlayerSend(boolean bPlayerSend) {
        this.bPlayerSend = bPlayerSend;
    }

    public boolean isPlayerHasTurn(int index) {
        return ArrayPlayer[index].isbHasTurn();
    }

    public void setPlayerHasTurn(int index, boolean isHasTurn) {
        ArrayPlayer[index].setbHasTurn(isHasTurn);
    }
    // TEST //
    int typeTemp = -1;
    int numberTemp = -1;

    private void TestTemp(Graphics g) {
        // TEST //
        g.drawString(Integer.toString(whoHasTurn), 10, 100);
        g.drawString(Integer.toString(fisrtCardType), 10, 200);
        g.drawString(Integer.toString(whoHasFirstTurn), 10, 300);
        g.drawString(Integer.toString(numberTemp), 10, 400);
        g.drawString(Integer.toString(typeTemp), 10, 500);

        g.drawString(Integer.toString(ArrayPlayer[0].getScore()), 10, 600);
        g.drawString(Integer.toString(ArrayPlayer[1].getScore()), 40, 600);
        g.drawString(Integer.toString(ArrayPlayer[2].getScore()), 70, 600);
        g.drawString(Integer.toString(ArrayPlayer[3].getScore()), 110, 600);

        if (IsBrokenHeart) {
            g.drawString("Broken heart", 10, 700);
        }
    }

    public void Update() {
        if (ArrayPlayer[iPlayerUpdate].UpdatedCard) {
            iPlayerUpdate = (iPlayerUpdate + 1) % 4;
        }
        ArrayPlayer[iPlayerUpdate].Update();
        for (int i = 0; i < ArrayPlayer.length; i++) {
            ArrayPlayer[i].Update();
        }
    }

    public void Draw(Graphics g) {
        DrawBackground(g, GlobalSettings.ScreenWidth, GlobalSettings.ScreenHeight);
        DrawPlayerName(g);
        for (int i = 0; i < ArrayPlayer.length; i++) {
            ArrayPlayer[i].Draw(g);
        }

        // Ve mang card dduoc nhan
        for (int i = 0; i < CardReceived.length; i++) {
            if (CardReceived[i] != null) {
                CardReceived[i].setPosition(GlobalSettings.PosToDrawReceivedCard[i]);
                CardReceived[i].Draw(g);
            }
        }
        TestTemp(g);
    }

        private boolean isFinishedMakeDeal = false;

    /*
     * kiem tra xem chia bai xong chua
     */
    public void makeDealFinished() {
        for (int i = 0; i < ArrayPlayer.length; i++) {
            if (ArrayPlayer[i].nCardUpdate < 12) {
                return;
            }
        }
        isFinishedMakeDeal = true;
    }

    /**
     * @return the isFinishedMakeDeal
     */
    public boolean isIsFinishedMakeDeal() {
        return isFinishedMakeDeal;
    }

    private void sortListCard(int iPlayer) {
        ArrayPlayer[iPlayer].sortListCard();
    }
}
